#include "stdafx.h"
#include "AreaLight.h"

namespace PhotonMapping
{

AreaLight::AreaLight(const Math::Vector3& p_P0, const Math::Vector3& p_P1, 
					 const Math::Vector3& p_P2, const Math::Vector3& p_P3,
					 const Color& p_Color, const float p_Intensity)
	: m_P0(p_P0), m_P1(p_P1), m_P2(p_P2), m_P3(p_P3), 
	  ILight(p_P0 + (p_P2 - p_P0) * 0.5f, p_Color, p_Intensity)
{
	m_Normal = Cross(p_P1 - p_P0, p_P3 - p_P0);
	m_Normal.Normalize();
	m_UsePM = false;

	m_Area = Cross(p_P1 - p_P0, p_P3 - p_P0) * m_Normal;
}

void AreaLight::CreateProjectionMap(const ScenePtr p_Ptr)
{
	m_UsePM = true;
}

const Math::Ray AreaLight::SampleLightRay(float p_U1, float p_U2)
{
	using namespace Math;

	Ray lightRay;

	// sample a random position on the light's area
	Vector3 diff = m_P2 - m_P0;
	diff.m_X *= Random(1.0f);
	diff.m_Y *= Random(1.0f);
	diff.m_Z *= Random(1.0f);
	lightRay.m_Position = m_P0 + diff;

	// sample random direction
	const float phi = PI * 2.0f * Random(1.0f);
	const float theta = ACos(Sqrt(1.0f - Random(1.0f)));

	// make coord frame coefficients (z in normal direction)
	const float x = Cos(phi) * Sin(theta);
	const float y = Sin(phi) * Sin(theta);
	const float z = Cos(theta);

	// make coord frame
	Vector3 tangent(GetTangent(m_Normal));

	// make vector from frame times coefficients
	lightRay.m_Direction = (tangent * x) + (Cross(tangent, m_Normal) * y) + (m_Normal * z);
	lightRay.m_Direction.Normalize();
	
	return lightRay;
}

const Color AreaLight::GetMaxFlux()
{
	return GetColor() * GetIntensity() * m_Area;
}

}
